/*
    根据内核链表封装的函数
*/
#include "list_func.h"

// 定义及初始化用户节点
ElemNode *newElemNode(ElemType val)
{
    ElemNode *p = (ElemNode *)malloc(sizeof(ElemNode));
    if (p == NULL) // 申请内存失败
    {
        printf("malloc newNode error\n");
        return NULL;
    }
    // 为数据分配内存，并复制 val 的内容
    p->data = (char *)malloc(strlen(val) + 1); // +1 为了存储字符串结束符 '\0'
    if (p->data == NULL)
    {
        printf("malloc data error\n");
        free(p); // 释放之前分配的内存
        return NULL;
    }
    strcpy(p->data, val); // 复制 val 的内容到新分配的内存

    // 初始化链表节点的指针域
    INIT_LIST_HEAD(&(p->list));
    return p;
}

// 创建头节点(无数据)
ElemNode *headNode()
{
    // 创建一个头结点
    ElemNode *head = newElemNode("-1"); // 头结点不需要数据域 一般写-1

    // 调用内核链表中的接口初始化方法  初始化头结点的指针域
    INIT_LIST_HEAD(&(head->list));

    return head;
}

// 遍历 打印节点数据
void traverse(ElemNode *head)
{
    struct list_head *pos; // 指针域的 地址
    // 遍历 (不能修改 pos)
    list_for_each(pos, &(head->list))
    {
        ElemNode *Node = list_entry(pos, ElemNode, list);

        printf("%s\n", Node->data);
    }
}

// 插入节点(尾插法)
void insert_tail(ElemNode *head, ElemType val)
{
    ElemNode *new = newElemNode(val);
    list_add_tail(&(new->list), &(head->list)); // 调用内核链表库中的函数
}

// 插入节点(头插法)
void insert_head(ElemNode *head, ElemType val)
{
    ElemNode *new = newElemNode(val);
    list_add(&(new->list), &(head->list));
}

// 删除指定数据的节点
void del_node(ElemNode *head, ElemType deldata)
{
    struct list_head *pos; // 指针域的 地址
    struct list_head *n;

    /* 根据小结构体删除节点 */
    list_for_each_safe(pos, n, &(head->list)) // 遍历 (可以修改pos)
    {
        // p是小结构体  Node是大结构体
        ElemNode *Node = list_entry(pos, ElemNode, list); // list_entry() 根据小结构体计算大结构体的地址
        if (Node->data == deldata)                        // 当找到 大结构体数据为deldata的节点时
        {
            list_del(pos); // 调用内核链表中的删除函数
        }
    }
    free(list_entry(pos, ElemNode, list)); // 手动释放 大结构体内存
}

// 查找指定数据(对比账号密码)
int search_data(ElemNode *head, ElemType data) // 找到返回1, 没找到返回0
{
    struct list_head *pos2;
    struct list_head *n2;

    int found = 0;

    /* 根据小结构体查找节点 */
    list_for_each_safe(pos2, n2, &(head->list))
    {
        ElemNode *Node2 = list_entry(pos2, ElemNode, list);
        char *str2 = strdup(Node2->data); // 创建Node->data的副本

        if (strcmp(str2, data) == 0)
        {
            found = 1;
            break; // 找到后退出循环
        }

        // 只在调试时打印，或者在找到不匹配时打印
        // printf("\n str-%s  data-%s ",str2,data);
        // printf("str-%ld  data-%ld ",strlen(str2),strlen(data));

        free(str2); // 释放副本
    }

    return found;
}

// 查找指定数据(账号)的节点
int search_account(ElemNode *head, ElemType data)
{
    struct list_head *pos;
    struct list_head *n;

    int found = 0;

    /* 根据小结构体查找节点 */
    list_for_each_safe(pos, n, &(head->list))
    { // 遍历
        ElemNode *Node = list_entry(pos, ElemNode, list);
        char *str = strdup(Node->data); // 创建Node->data的副本
        char *token;
        char *last = NULL; // strtok_r的额外参数

        token = strtok_r(str, "#", &last);
        if (strcmp(token, data) == 0)
        { // 比较账号
            found = 1;
            free(str); // 释放副本
            break;     // 找到账号后退出循环
        }
        free(str); // 释放副本
    }

    return found;
}

// 销毁链表
void destroy_allToList(ElemNode *head)
{
    ElemNode *pos, *n;

    // 遍历并删除链表中的每个节点
    list_for_each_entry_safe(pos, n, &(head->list), list)
    {
        // 如果节点的data是动态分配的，需要先释放
        if (pos->data)
        {
            free(pos->data); // 释放节点数据
        }
        list_del(&(pos->list)); // 从链表中删除节点
        free(pos);              // 释放节点本身
    }

    free(head); // 释放头结点
}